package com.bacel.nb.product.web.filter;

import org.jasig.cas.client.proxy.*;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.ReflectUtils;
import org.jasig.cas.client.validation.AbstractTicketValidationFilter;
import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * Created by liyu on 17/1/3.
 */
public class MyTicketValidationFilter extends AbstractTicketValidationFilter {

    private static final String EXCLUDE_PATHS = "ExcludePaths"; //过滤列表

    private static final String[] RESERVED_INIT_PARAMS = new String[]{"proxyGrantingTicketStorageClass", "proxyReceptorUrl", "acceptAnyProxy", "allowedProxyChains", "casServerUrlPrefix", "proxyCallbackUrl", "renew", "exceptionOnValidationFailure", "redirectAfterValidation", "useSession", "serverName", "service", "artifactParameterName", "serviceParameterName", "encodeServiceUrl", "millisBetweenCleanUps", "hostnameVerifier", "encoding", "config"};
    private static final int DEFAULT_MILLIS_BETWEEN_CLEANUPS = 60000;
    private String proxyReceptorUrl;
    private Timer timer;
    private TimerTask timerTask;
    private int millisBetweenCleanUps;
    private ProxyGrantingTicketStorage proxyGrantingTicketStorage = new ProxyGrantingTicketStorageImpl();

    /**
     * 添加属性，这里用来存放不过滤地址正则表达式，可以根据自己需求定制---1
     */
    private String strExcludeFile;
    private String[] arrExcludeFile = null;

    public MyTicketValidationFilter() {

        setStrExcludeFile("");
    }

    protected void initInternal(FilterConfig filterConfig) throws ServletException {
        this.setProxyReceptorUrl(this.getPropertyFromInitParams(filterConfig, "proxyReceptorUrl", (String)null));
        String proxyGrantingTicketStorageClass = this.getPropertyFromInitParams(filterConfig, "proxyGrantingTicketStorageClass", (String)null);
        if(proxyGrantingTicketStorageClass != null) {
            this.proxyGrantingTicketStorage = (ProxyGrantingTicketStorage) ReflectUtils.newInstance(proxyGrantingTicketStorageClass, new Object[0]);
            if(this.proxyGrantingTicketStorage instanceof AbstractEncryptedProxyGrantingTicketStorageImpl) {
                AbstractEncryptedProxyGrantingTicketStorageImpl p = (AbstractEncryptedProxyGrantingTicketStorageImpl)this.proxyGrantingTicketStorage;
                String cipherAlgorithm = this.getPropertyFromInitParams(filterConfig, "cipherAlgorithm", "DESede");
                String secretKey = this.getPropertyFromInitParams(filterConfig, "secretKey", (String)null);

                p.setCipherAlgorithm(cipherAlgorithm);

                try {
                    if(secretKey != null) {
                        p.setSecretKey(secretKey);
                    }
                } catch (Exception var7) {
                    throw new RuntimeException(var7);
                }
            }
        }

        //设置过滤url
        this.setStrExcludeFile(getPropertyFromInitParams(filterConfig, EXCLUDE_PATHS, ""));

        this.log.trace("Setting proxyReceptorUrl parameter: " + this.proxyReceptorUrl);
        this.millisBetweenCleanUps = Integer.parseInt(this.getPropertyFromInitParams(filterConfig, "millisBetweenCleanUps", Integer.toString('\uea60')));
        super.initInternal(filterConfig);
    }

    public void init() {
        super.init();
        CommonUtils.assertNotNull(this.proxyGrantingTicketStorage, "proxyGrantingTicketStorage cannot be null.");
        if(this.timer == null) {
            this.timer = new Timer(true);
        }

        if(this.timerTask == null) {
            this.timerTask = new CleanUpTimerTask(this.proxyGrantingTicketStorage);
        }

        this.timer.schedule(this.timerTask, (long)this.millisBetweenCleanUps, (long)this.millisBetweenCleanUps);

        if (strExcludeFile != null && strExcludeFile.trim().length() > 0) {
            arrExcludeFile = strExcludeFile.split(";");
        }
    }

    protected final TicketValidator getTicketValidator(FilterConfig filterConfig) {
        String allowAnyProxy = this.getPropertyFromInitParams(filterConfig, "acceptAnyProxy", (String)null);
        String allowedProxyChains = this.getPropertyFromInitParams(filterConfig, "allowedProxyChains", (String)null);
        String casServerUrlPrefix = this.getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", (String)null);
        Object validator;
        if(!CommonUtils.isNotBlank(allowAnyProxy) && !CommonUtils.isNotBlank(allowedProxyChains)) {
            validator = new Cas20ServiceTicketValidator(casServerUrlPrefix);
        } else {
            Cas20ProxyTicketValidator additionalParameters = new Cas20ProxyTicketValidator(casServerUrlPrefix);
            additionalParameters.setAcceptAnyProxy(this.parseBoolean(allowAnyProxy));
            additionalParameters.setAllowedProxyChains(CommonUtils.createProxyList(allowedProxyChains));
            validator = additionalParameters;
        }

        ((Cas20ServiceTicketValidator)validator).setProxyCallbackUrl(this.getPropertyFromInitParams(filterConfig, "proxyCallbackUrl", (String)null));
        ((Cas20ServiceTicketValidator)validator).setProxyGrantingTicketStorage(this.proxyGrantingTicketStorage);
        ((Cas20ServiceTicketValidator)validator).setProxyRetriever(new Cas20ProxyRetriever(casServerUrlPrefix, this.getPropertyFromInitParams(filterConfig, "encoding", (String)null)));
        ((Cas20ServiceTicketValidator)validator).setRenew(this.parseBoolean(this.getPropertyFromInitParams(filterConfig, "renew", "false")));
        ((Cas20ServiceTicketValidator)validator).setEncoding(this.getPropertyFromInitParams(filterConfig, "encoding", (String)null));
        HashMap additionalParameters1 = new HashMap();
        List params = Arrays.asList(RESERVED_INIT_PARAMS);
        Enumeration e = filterConfig.getInitParameterNames();

        while(e.hasMoreElements()) {
            String s = (String)e.nextElement();
            if(!params.contains(s)) {
                additionalParameters1.put(s, filterConfig.getInitParameter(s));
            }
        }

        ((Cas20ServiceTicketValidator)validator).setCustomParameters(additionalParameters1);
        ((Cas20ServiceTicketValidator)validator).setHostnameVerifier(this.getHostnameVerifier(filterConfig));
        return (TicketValidator)validator;
    }

    public void destroy() {
        super.destroy();
        this.timer.cancel();
    }

    protected final boolean preFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        String requestUri = request.getRequestURI();

        //过滤
        PathMatcher matcher = new AntPathMatcher();
        if(arrExcludeFile != null){
            for(String excludePath : arrExcludeFile){
                boolean flag = matcher.match(excludePath, requestUri);
                if(!flag){
                    flag = requestUri.indexOf(excludePath) > 0;
                }
                if(flag){
                    this.log.debug("excludePath " + excludePath + " pass sso authentication in validationFilter");
                    filterChain.doFilter(request, response);
                    return false;
                }
            }
        }

        if(!CommonUtils.isEmpty(this.proxyReceptorUrl) && requestUri.endsWith(this.proxyReceptorUrl)) {
            try {
                CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage);
                return false;
            } catch (RuntimeException var8) {
                this.log.error(var8.getMessage(), var8);
                throw var8;
            }
        } else {
            return true;
        }
    }

    public final void setProxyReceptorUrl(String proxyReceptorUrl) {
        this.proxyReceptorUrl = proxyReceptorUrl;
    }

    public void setProxyGrantingTicketStorage(ProxyGrantingTicketStorage storage) {
        this.proxyGrantingTicketStorage = storage;
    }

    public void setTimer(Timer timer) {
        this.timer = timer;
    }

    public void setTimerTask(TimerTask timerTask) {
        this.timerTask = timerTask;
    }

    public void setMillisBetweenCleanUps(int millisBetweenCleanUps) {
        this.millisBetweenCleanUps = millisBetweenCleanUps;
    }

    public void setStrExcludeFile(String strExcludeFile) {
        this.strExcludeFile = strExcludeFile;
    }
}
